package net.j4love.algorithm.link;

/**
 * @author he peng
 * @create 2017/9/26 10:45
 * @see
 */
public class SingleDirectionLinkedList<T> {

    private Node firstNode;
    private Node lastNode;
    private int size;

    public boolean deleteLast() {
        if (this.size == 1) {
            this.firstNode = null;
            return true;
        }
        Node node = this.firstNode;
        for (int i = 0 ; i < this.size - 1 ; i++) {
            node = node.next;
        }
        node.next = null;
        this.lastNode = node;
        this.size--;
        return true;
    }

    public boolean addFirst(T t) {
        if (null == this.firstNode) {
            this.firstNode = new Node(t,null);
        } else {
            Node oldFirstNode = this.firstNode;
            this.firstNode = new Node(t,oldFirstNode);
        }
        this.size++;
        return true;
    }

    public boolean addLast(T t) {
        Node newLastNode = new Node(t, null);
        if (null == this.firstNode) {
            this.firstNode = newLastNode;
        } else if (null == this.lastNode) {
            this.lastNode = newLastNode;
            this.firstNode.setNext(newLastNode);
        } else {
            Node oldLastNode = this.lastNode;
            oldLastNode.setNext(newLastNode);
            this.lastNode = newLastNode;
        }
        this.size++;
        return true;
    }

    public boolean add(int index , T t) {
        if (index == 0) {
            this.firstNode = new Node(t,null);
            return true;
        }
        Node node = this.firstNode;
        Node previousNode = null;
        for (int i = 1 ; i <= index ; i++) {
            previousNode = node;
            node = node.next;
        }
        Node newNode = new Node(t, node);
        previousNode.setNext(newNode);
        this.size++;
        return true;
    }

    public T get(int index) {
        if (index == 0) {
            return this.firstNode.value;
        }
        Node node = this.firstNode;
        for (int i = 0 ; i < index ; i++) {
            node = node.next;
        }
        return node.value;
    }

    public int getSize() {
        return size;
    }

    public T getFirst() {
        return firstNode.getValue();
    }

    public T getLast() {
        if (null == this.lastNode) {
            return this.firstNode.getValue();
        }
        return lastNode.getValue();
    }

    private class Node {

        private T value;
        private Node next;

        public Node(T value, Node next) {
            this.value = value;
            this.next = next;
        }

        public T getValue() {
            return value;
        }

        public Node setValue(T value) {
            this.value = value;
            return this;
        }

        public Node getNext() {
            return next;
        }

        public Node setNext(Node next) {
            this.next = next;
            return this;
        }
    }
}
